package com.novaed.game.backend;

import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.novaed.game.backend.Paths;
import com.novaed.game.backend.Profile;

public class Player implements IGame {

	protected String USER;
	protected String PID;

	public Player() {}
	public Player(String User, String PID) {
		setOnlineUser(User, PID);
	}

	public void createNewUser(String Username, String Password, String firstName, String lastName) {

		try {
			DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
			Document users = docBuilder.parse(userXML);
			Element root = users.getDocumentElement();


			if (!isExisting(Username)) {
				System.out.println(Username + " is available!");
				System.out.println("Proceeding to create...");
				
				Element username = users.createElement("username");
				Element password = users.createElement("password");
				Element firstname = users.createElement("firstname");
				Element lastname = users.createElement("lastname");

				username.setTextContent(Username);
				password.setTextContent(Password);
				firstname.setTextContent(firstName);
				lastname.setTextContent(lastName);

				Element profile = users.createElement("profile");
				profile.setAttribute("pid", String.valueOf(Integer.valueOf(Username)));

				profile.appendChild(username);
				profile.appendChild(password);
				profile.appendChild(firstname);
				profile.appendChild(lastname);

				root.appendChild(profile);

				users.replaceChild(root, root);

				Transformer tFormer = TransformerFactory.newInstance().newTransformer();
				tFormer.setOutputProperty(OutputKeys.METHOD, "xml");
				tFormer.setOutputProperty(OutputKeys.INDENT, "yes");
				tFormer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
				tFormer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");

				Source source = new DOMSource(users);
				Result result = new StreamResult(userXML);
				tFormer.transform(source, result);
				
				newScoreSheet(String.valueOf(Integer.valueOf(Username)));

				System.out.println("Finished creating new user novaed" + Username + "!");
			}


		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (TransformerConfigurationException e) {
			e.printStackTrace();
		} catch (TransformerFactoryConfigurationError e) {
			e.printStackTrace();
		} catch (TransformerException e) {
			e.printStackTrace();
		}

	}

	//TODO remove child-node 'profile'
	public void deleteUser(String Username, String Password) {
		
		Node detail = null;
		Element user = null;

		try {

			DocumentBuilder dBuilder = docFactory.newDocumentBuilder();
			Document doc = dBuilder.parse(Paths.getUsers());

			doc.getDocumentElement().normalize();

			NodeList profileList = doc.getElementsByTagName("profile");

			for (int i = 0; i <= profileList.getLength() - 1; i++) {

				detail = profileList.item(i);
				user = (Element) detail;

				if (user.getElementsByTagName("username").item(0)
						.getTextContent().equals(Username)) {

					for (int j = 0; j < profileList.getLength(); j++) {
						
						NodeList n = detail.getChildNodes();
						Node sub = n.item(j);
						
						if (sub.getNodeType() == Node.ELEMENT_NODE) {
							System.out.println(sub.getNodeName());
							System.out.println(sub.getTextContent());
							detail.removeChild(sub);
							user.removeAttribute("pid");
						}
						
					}

					break;
				}
				

			}

			TransformerFactory transformerFactory = TransformerFactory.newInstance();
			Transformer transformer = transformerFactory.newTransformer();
			transformer.setOutputProperty(OutputKeys.METHOD, "xml");
			transformer.setOutputProperty(OutputKeys.INDENT, "yes");
			transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
			transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
			DOMSource source = new DOMSource(doc);
			StreamResult result = new StreamResult(userXML);
			transformer.transform(source, result);

		} catch (SAXException e) {
			System.err.println(e);
		} catch (IOException e) {
			System.err.println(e);
		} catch (ParserConfigurationException e) {
			System.err.println(e);
		} catch (NullPointerException e) {
			System.err.println(e);
		} catch (TransformerConfigurationException e) {
			System.err.println(e);
		} catch (TransformerException e) {
			System.err.println(e);
		}

	}

	public void setOnlineUser(String User, String PID) {
		this.USER = User;
		this.PID = PID;
	}

	public void setOnlineUser(String User) {
		this.USER = User;
	}

	public void setLastLevel(int score) {

		Profile online = new Profile(getOnlineUser(), getUserPID());

		if (score <= 15) {

			try {
				FileWriter appendScore = new FileWriter(online.getScoreSheet(), true);

				if (!online.getScoreSheet().exists()) {
					newScoreSheet(getUserPID());
					appendScore.write("\n" + String.valueOf(score));
					appendScore.close();
				}
				
				appendScore.write("\n" + String.valueOf(score));
				appendScore.close();

			} catch (IOException e) {
				System.err.println("** Class Name : Player");
				System.err.println("   Method Name : setLastLevel()");
				System.err.println("   try/catch block: IOException");
				System.err.println("**");
				System.err.println(online.getUserPID() + ".txt read error.");

			} catch (NullPointerException e) {
				System.err.println("** Class Name : Player");
				System.err.println("   Method Name : setLastLevel()");
				System.err.println("   try/catch block: NullPointerException ");
				System.err.println("**");
				System.err.println(Paths.getProfilePath() + online.getUserPID() + ".txt does not exist.");
			} catch (NumberFormatException e) {
				System.err.println("** Class Name : Player");
				System.err.println("   Method Name : setLastLevel()");
				System.err.println("   try/catch block: NumberFormatException ");
				System.err.println("**");
			}

		} else {
			// invalid input!
			System.err.println("invalid input!");
		}
	}
	
	public void newScoreSheet(String Username) {
			try {

				new BufferedWriter
				(new OutputStreamWriter(
						new FileOutputStream(
								Paths.getProfilePath() + 
								String.valueOf(Integer.valueOf(Username)) + ".txt"
							),"UTF-8"
						)
				);

			} catch (IOException e) {
				System.err.println("** Class Name : Profile");
				System.err.println("   Method Name : ScoreSheet()");
				System.err.println("   try/catch block: IOException");
				System.err.println("**");
				System.err.println("Write to file " + getUserPID() + ".txt generated an error.");
			}

	}

	public boolean isExisting(String Username) {

		Element pid = null;
		DocumentBuilder docBuilder = null;
		Document users = null;

		try {
			docBuilder = docFactory.newDocumentBuilder();
			users = docBuilder.parse(userXML);
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		}
		
		NodeList profilesList = users.getElementsByTagName("profile");

		for (int i = 0; i <= profilesList.getLength() - 1; i++) {
			Node profileNode = profilesList.item(i);
			pid = (Element) profileNode;

			if (pid.getAttribute("pid").equals(String.valueOf(Integer.valueOf(Username)))) {
				System.err.println(Username + " already exists!");
				return true;
			}

		}
		return false;
	}

	public boolean isOnline() {
		if (getOnlineUser() == null) {
			return false;
		}
		return true;
	}

	public String getOnlineUser() {
		return USER;
	}

	public String getUserPID() {
		return PID;
	}
}